home *** CD-ROM | disk | FTP | other *** search
/ DOpus Plus / DOpus Plus.iso / Enhancements / FTPBatch / ARexx / FTPBatchDownload.dopus5 < prev    next >
Encoding:
Text File  |  1998-10-25  |  16.1 KB  |  544 lines

  1. /* $VER: FTPBatchDownload.dopus 4.1 (25.10.98) (C) by Martin Steigerwald
  2. */
  3.  
  4. OPTIONS RESULTS
  5. IF ~SHOW('L','rexxsupport.library') THEN CALL ADDLIB('rexxsupport.library',0,-30,0)
  6.  
  7. PARSE ARG opus listerport handle defaultmaxconnections config.requesters ' "' config.logging '" ' '"' destdir '" ' whichentries deletemode
  8.  
  9. opus=STRIP(opus)
  10. listerport=STRIP(listerport)
  11. handle=STRIP(handle)
  12. defaultmaxconnections=STRIP(defaultmaxconnections)
  13. config.requesters=STRIP(config.requesters)
  14. whichentries=STRIP(whichentries)
  15. deletemode=STRIP(deletemode)
  16.  
  17. /* --- DELAY ---
  18.    Here you can specify how long, in 1/50 seconds, FTPBatchDownload should
  19.    wait when all FTP listers are busy.
  20.    I recommend: Don't go below 25.
  21.    Raise this value when FTPBatchDownload eats to much CPU time on your system.
  22. */
  23.  
  24. config.delay=25
  25.  
  26. ADDRESS VALUE opus
  27.  
  28. IF handle=0 | listerport=0 THEN DO
  29.     Request('"ERROR: No batch lister given!" OK')
  30. END
  31.  
  32. portnr=SUBSTR(listerport, POS('.',listerport)+1)
  33. appname='FTPBatchDownload'
  34. portname=appname'.'portnr
  35. lf='0a'X
  36. debugging=0 /* debuginfo? 2=annoy console device 1=low 0=none */
  37. listermode=2 /* open ftp listers iconified? 2=invisible 1=iconofied 0=full */
  38.  
  39. IF ~OPENPORT(portname) THEN DO
  40.     DOPUSREQUEST '"'appname': Couldnt open port" OK'
  41.     EXIT
  42. END
  43.  
  44. /* OPTIONS FAILAT 11    */
  45.  
  46. nr=1
  47.  
  48. AddLog('')
  49. AddLog('STATUS: Started FTPBatchDownload.')
  50.  
  51. DO FOREVER
  52.  
  53.     /* busy mode & lister closed? */
  54.     LISTER QUERY handle PATH
  55.     IF RC=10 THEN DO
  56.         LEAVE
  57.     END
  58.  
  59.     /* collectentries */
  60.  
  61.     CollectEntries()
  62.  
  63.     LISTER SET handle BUSY OFF
  64.     IF deletemode='AUTODOWNLOAD' THEN DO
  65.         LISTER QUERY handle PATH
  66.         IF RC=0 THEN DO
  67.             LISTER CLOSE handle
  68.         END
  69.     END
  70.  
  71.     /* batchdownloadsystem(TM) ;-) */
  72.  
  73.     /* something to download? */
  74.     IF entries>0 THEN DO
  75.         /* not more connections than entries */
  76.         IF defaultmaxconnections>entries THEN DO
  77.             maxconnections=entries
  78.         END
  79.         ELSE DO
  80.             maxconnections=defaultmaxconnections
  81.         END
  82.         IF maxconnections=1 THEN DO
  83.             returncode=DownloadOneByOne()
  84.             /* leave script when returncode=0 */
  85.             IF returncode=0 THEN entries=0
  86.         END
  87.         ELSE DO
  88.             returncode=DownloadThemAllAtOnce() /* ;-) */
  89.             /* leave loop when returncode=0 */
  90.             IF returncode=0 THEN entries=0
  91.         END /* ELSE maxconnections */
  92.     END /* IF entries */
  93.  
  94.     IF entries=0 | deletemode~=='DELETEENTRIES' | whichentries~='ALL' THEN DO
  95.         LEAVE
  96.     END
  97.  
  98. END /* DO FOREVER */
  99.  
  100. CLOSEPORT(portname)
  101.  
  102.  
  103.  
  104. EXIT
  105.  
  106. /**************************/
  107. /* DownloadThemAllAtOnce  */
  108. /**************************/
  109.  
  110. DownloadThemAllAtOnce:
  111.  
  112.     /* Open all FTP listers */
  113.     success=OpenAllFTPListers()
  114.     returncode=1
  115.  
  116.     IF success=1 THEN DO
  117.         ec=0 ; lc=0 /* entrycounter, listercounter */
  118.  
  119.         /* download loop */
  120.         DO FOREVER
  121.             /* are all listers ready with their work? */
  122.             ready=AllFTPListersReady()
  123.             /* a lister is closed! */
  124.             IF ready='closed' THEN DO
  125.                 returncode=0
  126.                 Request('"ERROR: A FTP lister has been closed. Exiting" OK')
  127.                 LEAVE
  128.             END
  129.  
  130.             /* are we done? */
  131.             IF ready=1 & ec>=entries THEN LEAVE /* YES! ;-) */
  132.  
  133.             /* check for the next free lister */
  134.             lc=CheckNextFreeFTPLister()
  135.             /* a lister is closed! */
  136.             IF lc='closed' THEN DO
  137.                 returncode=0
  138.                 Request('"ERROR: A FTP lister has been closed. Exiting" OK')
  139.                 LEAVE
  140.             END
  141.  
  142.             /* whats going on, lister? */
  143.             LISTER QUERY ftphandle.lc VALUE 'status'
  144.             status=RESULT
  145.  
  146.             IF config.requesters=='QUIET' THEN DO
  147.                 'COMMAND WAIT SOURCE' ftphandle.lc 'FTPSetVar Quiet ON'
  148.             END
  149.  
  150.             /* downloaded something? */
  151.             IF status=='download' THEN DO
  152.                 success=AfterDownload()
  153.                 IF success=0 THEN returncode=0
  154.                 IF success='abort' THEN DO
  155.                     returncode=0
  156.                     LEAVE
  157.                 END
  158.             END
  159.             /* correct directory set? */
  160.             ELSE IF status='currentdir' THEN DO
  161.                 StartDownload()
  162.             END
  163.             /* already connected? */
  164.             ELSE IF status='connect' THEN DO
  165.                 SetCurrentDir()
  166.             END
  167.             /* preparing new download */
  168.             ELSE IF ec<entries THEN DO
  169.                 success=NewDownload()
  170.                 IF success=0 THEN returncode=0
  171.                 IF success='abort' THEN DO
  172.                     returncode=0
  173.                     LEAVE
  174.                 END
  175.             END
  176.         END /* DO download loop*/
  177.  
  178.     END
  179.  
  180.     /* clean up */
  181.     DO i=1 TO maxconnections
  182.         IF ftphandle.i ~= 0 THEN LISTER CLOSE ftphandle.i
  183.     END
  184. RETURN returncode
  185.  
  186. OpenAllFTPListers:
  187.     success=1
  188.     DO i=1 TO maxconnections
  189.         ftphandle.i=0
  190.     END
  191.     DO i=1 TO maxconnections
  192.         IF listermode=0 THEN LISTER NEW
  193.         IF listermode=1 THEN LISTER NEW ICONIFY
  194.         IF listermode=2 THEN LISTER NEW INVISIBLE
  195.         ftphandle.i=RESULT
  196.         IF ftphandle.i=0 THEN DO
  197.             Request('"ERROR: Couldnt open new lister for ftp!" OK')
  198.             success=0
  199.             LEAVE
  200.         END
  201.         LISTER WAIT ftphandle.i QUICK
  202.         LISTER SET ftphandle.i TITLE appname'.'i
  203.         LISTER SET ftphandle.i VALUE 'status' 'new'
  204.         LISTER QUERY ftphandle.i VALUE 'ftpsite' '///'
  205.         LISTER QUERY ftphandle.i VALUE 'srcpathname' '///'
  206.  
  207.         LISTER REFRESH ftphandle.i FULL
  208.         IF config.requesters=='QUIET' THEN DO
  209.          /*   LISTER SET ftphandle.i SOURCE */
  210.             'COMMAND WAIT SOURCE' ftphandle.i 'FTPSetVar Quiet 1'
  211.          /*   LISTER SET ftphandle.i OFF */
  212.         END
  213.     END /* DO maxconnections */
  214. RETURN success
  215.  
  216. AllFTPListersReady:
  217.     ready=1
  218.     DO lccheck=1 TO maxconnections
  219.         LISTER QUERY ftphandle.lccheck VALUE 'status'
  220.         IF RC=10 THEN DO
  221.             ready='closed'
  222.             LEAVE
  223.         END
  224.         IF RESULT~='ready' THEN DO
  225.             ready=0
  226.         END
  227.         IF debugging>=2 THEN DO
  228.             SAY 'STATUS   status:' RESULT 'lister:' lccheck 'entrycounter:' ec
  229.         END
  230.     END /* DO are all ready? */
  231. RETURN ready
  232.  
  233. CheckNextFreeFTPLister:
  234.     closedlisters=0 ; allclosed=0
  235.     lastlc=lc
  236.     DO FOREVER
  237.         lc=lc+1
  238.         IF lc>maxconnections THEN lc=1
  239.  
  240.         LISTER QUERY ftphandle.lc BUSY
  241.  
  242.         IF RESULT=0 THEN LEAVE
  243.         IF lc=lastlc THEN DO
  244.             IF debugging>=1 THEN DO
  245.                 SAY 'DELAY    lister:' lc
  246.             END
  247.             DELAY(config.delay) /* dont overuse CPU power, no busy loop ;-) */
  248.         END
  249.         /* lister closed? */
  250.         IF RC=10 THEN DO
  251.             lc='closed'
  252.             LEAVE
  253.         END /* IF lister closed? */
  254.     END /* check for next free lister */
  255. RETURN lc
  256.  
  257. AfterDownload:
  258.     LISTER WAIT ftphandle.lc QUICK
  259.     success_afterdownload=1
  260.     LISTER QUERY ftphandle.lc VALUE 'entry'
  261.     actentry=RESULT
  262.     IF debugging>=1 THEN DO
  263.         SAY 'READY    lister:' lc 'ftpsite:' ftpsite 'downloaded entry:' entry.actentry.name
  264.     END
  265.     achar=RIGHT(destdir,1)
  266.     IF achar~==':' & achar~=='/' THEN DO
  267.         destfile=destdir'/'entry.actentry.name
  268.     END
  269.     ELSE DO
  270.         destfile=destdir || entry.actentry.name
  271.     END
  272.  
  273.     IF ~EXISTS(destfile) THEN DO
  274.         success_afterdownload=0
  275.         AddLog('ERROR: Can not find local file »destfile«!')
  276.         abort=DownloadFailed(entry.actentry.name)
  277.         IF abort=0 THEN success_afterdownload='abort'
  278.     END
  279.     commentstr=WORD(STATEF(destfile),8)
  280.     IF UPPER(LEFT(commentstr,16))=='TRANSFER ABORTED' THEN DO
  281.         success_afterdownload=0
  282.         Addlog('ERROR: Found »Transfer Aborted» in comment of »'destfile'«')
  283.         abort=DownloadFailed(entry.actentry.name)
  284.         IF abort=0 THEN success_afterdownload='abort'
  285.     END
  286.  
  287.     IF actentry~=0 & deletemode='DELETEENTRIES' THEN DO
  288.         IF success_afterdownload=1 THEN DO
  289.             LISTER QUERY handle PATH
  290.             IF RC=0 THEN DO
  291.                 'COMMAND WAIT SOURCE' handle ' DELETE "'entry.actentry.name'"'
  292.             END
  293.         END
  294.     END
  295.     AddLog('STATUS: #'lc 'Successfully downloaded entry »'entry.actentry.name'«.')
  296.     LISTER SET ftphandle.lc VALUE 'status' 'ready'
  297. RETURN success_afterdownload
  298.  
  299. StartDownload:
  300.     LISTER WAIT ftphandle.lc QUICK
  301.     LISTER QUERY ftphandle.lc VALUE 'entry'
  302.     actentry=RESULT
  303.     splitok=SplitURL(entry.actentry.comment)
  304.     /* we don't URL check here. It has been checked in StartDownload
  305.        already. */
  306.     destfilename=entry.actentry.name
  307.     LISTER SET ftphandle.lc VALUE 'status' 'download'
  308.     IF debugging>=1 THEN DO
  309.         SAY 'DOWNLOAD lister:' lc 'ftpsite:' ftpsite 'entry:' entry.actentry.name
  310.     END
  311.     AddLog('STATUS: #'lc 'Downloading entry »'entry.actentry.name'«.')
  312.     'COMMAND SOURCE' ftphandle.lc 'COPYAS NAME="'srcfilename'" NEWNAME="'destfilename'" TO="'destdir'" QUIET'
  313. RETURN 1
  314.  
  315. SetCurrentDir:
  316.     LISTER WAIT ftphandle.lc QUICK
  317.     LISTER QUERY ftphandle.lc VALUE 'srcpathname'
  318.     srcpathname=RESULT
  319.     LISTER QUERY ftphandle.lc VALUE 'oldsrcpathname'
  320.     oldsrcpathname=RESULT
  321.     IF srcpathname~==oldsrcpathname THEN DO
  322.         IF debugging>=1 THEN DO
  323.             SAY 'CWD      lister:' lc 'ftpsite:' ftpsite 'path:' srcpathname
  324.         END
  325.         'COMMAND SOURCE' ftphandle.lc 'FTPCOMMAND QUIET CWD' srcpathname
  326.     END
  327.     LISTER SET ftphandle.lc VALUE 'status' 'currentdir'
  328. RETURN 1
  329.  
  330. NewDownload:
  331.     LISTER WAIT ftphandle.lc QUICK
  332.     success_newdownload=1
  333.     ec=ec+1
  334.     LISTER QUERY ftphandle.lc VALUE 'ftpsite'
  335.     oldftpsite=RESULT
  336.     LISTER QUERY ftphandle.lc VALUE 'srcpathname'
  337.     oldsrcpathname=RESULT
  338.     LISTER SET ftphandle.lc VALUE 'oldsrcpathname' oldsrcpathname
  339.     splitok=SplitURL(entry.ec.comment)
  340.     IF splitok=0 THEN DO
  341.         Request('"ERROR: Wrong URL »'entry.ec.comment'«!" OK')
  342.         success_newdownload=0
  343.         abort=DownloadFailed(entry.ec.name)
  344.         IF abort=0 THEN success_newdownload='abort'
  345.     END
  346.     ELSE DO
  347.         LISTER SET ftphandle.lc VALUE 'status' 'connect'
  348.         LISTER SET ftphandle.lc VALUE 'entry' ec
  349.         LISTER SET ftphandle.lc VALUE 'ftpsite' ftpsite
  350.         LISTER SET ftphandle.lc VALUE 'srcpathname' srcpathname
  351.  
  352.         IF ftpsite~==oldftpsite THEN DO /* new connect? */
  353.             IF debugging>=1 THEN DO
  354.                 SAY 'CONNECT  lister:' lc 'ftpsite:' ftpsite 'entry:' entry.ec.name 'oldftpsite:' oldftpsite
  355.             END
  356.             AddLog('STATUS: #'lc 'Connecting to »'ftpsite'«.')
  357.             'COMMAND FTPCONNECT LISTER ' ftphandle.lc 'HOST' ftpsite 'NOSCAN'
  358.         END /* IF new connect? */
  359.     END
  360. RETURN success_newdownload
  361.  
  362. /****************************/
  363. /* Download them one by one */
  364. /****************************/
  365.  
  366. DownloadOneByOne:
  367.     /* open lister */
  368.     returncode=1
  369.     IF listermode=0 THEN LISTER NEW
  370.     IF listermode=1 THEN LISTER NEW ICONIFY
  371.     IF listermode=2 THEN LISTER NEW INVISIBLE
  372.     ftphandle=RESULT
  373.     IF ftphandle=0 THEN DO
  374.        Request('"ERROR: Couldnt open new lister for ftp!" OK')
  375.        returncode=0
  376.     END
  377.     IF ftphandle~=0 THEN DO
  378.         LISTER WAIT ftphandle QUICK
  379.         LISTER SET ftphandle TITLE appname
  380.         LISTER REFRESH ftphandle FULL
  381.  
  382.         ftpsite='///'
  383.         srcpathname='///'
  384.  
  385.         /* download loop */
  386.         DO i=1 TO entries
  387.             LISTER QUERY ftphandle PATH
  388.             IF RC=10 THEN DO
  389.                 SAY "YES!"
  390.                 Request('"ERROR: The FTP lister has been closed!" OK')
  391.                 returncode=0
  392.                 LEAVE
  393.             END
  394.  
  395.             oldftpsite=ftpsite
  396.             oldsrcpathname=srcpathname
  397.             splitok=SplitURL(entry.i.comment)
  398.             IF splitok=0 THEN DO
  399.                 Request('"ERROR: Wrong URL »'entry.i.comment'«!" OK')
  400.                 returncode=0
  401.             END
  402.             ELSE DO
  403.                 destfilename=entry.i.name
  404.                 IF config.requesters=='QUIET' THEN DO
  405.                     'COMMAND WAIT SOURCE' ftphandle 'FTPSetVar Quiet 1'
  406.                 END
  407.  
  408.                 IF oldftpsite~==ftpsite THEN DO
  409.                     AddLog('STATUS: Connecting to »'ftpsite'«.')
  410.                     'COMMAND WAIT FTPCONNECT LISTER ' ftphandle 'HOST' ftpsite 'DIR "'srcpathname'" NOSCAN'
  411.                 END
  412.                 IF config.requesters=='QUIET' THEN DO
  413.                     'COMMAND WAIT SOURCE' ftphandle 'FTPSetVar Quiet 1'
  414.                 END
  415.  
  416.                 IF oldsrcpathname~==srcpathname THEN DO
  417.                     'COMMAND WAIT SOURCE' ftphandle 'FTPCOMMAND QUIET CWD' srcpathname
  418.                 END
  419.                 AddLog('STATUS: Downloading entry »'entry.i.name'«.')
  420.                 'COMMAND WAIT SOURCE' ftphandle 'COPYAS NAME="'srcfilename'" NEWNAME="'destfilename'" TO="'destdir'" QUIET'
  421.                 copyok=RESULT
  422.                 IF copyok=0 THEN DO
  423.                     returncode=0
  424.                     abort=DownloadFailed(entry.i.name)
  425.                     IF abort=0 THEN LEAVE
  426.                 END
  427.                 IF copyok=1 & deletemode=='DELETEENTRIES' THEN DO
  428.                     LISTER QUERY handle PATH
  429.                     IF RC=0 THEN DO
  430.                         'COMMAND WAIT SOURCE' handle ' DELETE "'entry.i.name'"'
  431.                     END
  432.                 END
  433.                 IF copyok=1 THEN DO
  434.                     AddLog('STATUS: Successfully downloaded entry »'entry.i.name'«.')
  435.                 END
  436.             END
  437.         END
  438.         LISTER CLOSE ftphandle
  439.     END
  440. RETURN returncode
  441.  
  442. /***************/
  443. /* Other stuff */
  444. /***************/
  445.  
  446. DownloadFailed: PROCEDURE EXPOSE config. lf
  447.     PARSE ARG file
  448.     abort=1
  449.     returncode=Request('"ERROR: Failed to download entry »'file'«!" OK|Abort')
  450.     IF returncode=0 THEN DO
  451.         abort=0
  452.     END
  453. RETURN abort
  454.  
  455. Request: PROCEDURE EXPOSE config.
  456.     PARSE ARG string
  457.     IF config.logging~=='' THEN DO
  458.         PARSE VAR string '"' errortext '"'
  459.         AddLog(errortext)
  460.         returncode=1
  461.     END
  462.     IF config.requesters='REQUESTERS' THEN DO
  463.         DOPUS REQUEST string
  464.         returncode=RC
  465.     END
  466. RETURN returncode
  467.  
  468.  
  469. AddLog: PROCEDURE EXPOSE config.logging
  470.     PARSE ARG string
  471.     IF config.logging~=='' THEN DO
  472.         IF EXISTS(config.logging'.log') THEN DO
  473.             res=OPEN('fh', config.logging'.log', 'APPEND')
  474.         END
  475.         ELSE DO
  476.             res=OPEN('fh', config.logging'.log', 'WRITE')
  477.         END
  478.         IF res=res THEN DO
  479.             IF string='' THEN DO
  480.                 WRITELN('fh', '')
  481.             END
  482.             ELSE DO
  483.                 IF POS(':',string)>0 & POS(':',string)<=7 THEN DO
  484.                     PARSE VAR string before ':' after
  485.                     string=before || ':' || COPIES(' ', 6-LENGTH(before)) || after
  486.                 END
  487.                 WRITELN('fh', DATE()' 'TIME()' - 'string)
  488.             END
  489.             CLOSE('fh')
  490.         END
  491.     END
  492. RETURN 1
  493.  
  494. /* splits URL into srcfilename, srcpathname and ftpsite */
  495. SplitURL: PROCEDURE EXPOSE srcfilename srcpathname ftpsite
  496.     PARSE ARG url
  497.     success=1
  498.     sep1=POS('//', url)
  499.     sep2=LASTPOS('/', url)
  500.     IF sep1~=0 & sep2~=0 & sep2-sep1-2>0 THEN DO
  501.         srcfilename=SUBSTR(url, sep2+1)
  502.         srcpathname=SUBSTR(url, sep1+2, sep2-sep1-2)
  503.         IF POS(':',srcpathname)=0 THEN DO
  504.             srcpathname='/'srcpathname
  505.         END
  506.         ftpsite=LEFT(url, sep1-1)
  507.     END
  508.     ELSE DO
  509.         success=0
  510.     END
  511. RETURN success
  512.  
  513.  
  514. CollectEntries:
  515.     LISTER SET handle BUSY ON
  516.     entries=0
  517.     IF whichentries='ALL' THEN DO
  518.         LISTER QUERY handle NUMENTRIES
  519.         entries=RESULT
  520.         /* something left? */
  521.         IF entries>0 THEN DO
  522.             DO i=1 TO entries
  523.                 LISTER QUERY handle ENTRY '#' || i-1 STEM entry.i.
  524.             END
  525.         END /* IF something left? */
  526.     END
  527.     ELSE IF whichentries='SELECTED' THEN DO
  528.         LISTER QUERY handle SELFILES STEM selectfiles.
  529.         entries=selectfiles.count
  530.         /* something selected? */
  531.         IF entries>0 THEN DO
  532.             DO i=1 TO entries
  533.                 j=i-1
  534.                 LISTER QUERY handle ENTRY '"'selectfiles.j'"' STEM entry.i.
  535.             END
  536.         END
  537.         ELSE DO
  538.             LISTER REQUEST handle '"You didnt select anything!" OK'
  539.         END
  540.     END /* IF whichentries */
  541.     LISTER SET handle BUSY OFF
  542. RETURN 0
  543.  
  544.